package cn.iocoder.yudao.module.trade.order.service.calculator;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.api.promotion.activity.enums.PromotionTypeEnum;
import cn.iocoder.yudao.module.api.promotion.fod.FirstOrderDiscountApi;
import cn.iocoder.yudao.module.api.promotion.fod.bo.FirstOrderDiscountBO;
import cn.iocoder.yudao.module.api.trade.order.enums.TradeOrderTypeEnum;
import cn.iocoder.yudao.module.trade.order.bo.TradePriceCalculateReqBO;
import cn.iocoder.yudao.module.trade.order.bo.TradePriceCalculateRespBO;
import cn.iocoder.yudao.module.trade.order.service.TradeOrderQueryService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

import static cn.iocoder.yudao.module.trade.order.service.calculator.TradePriceCalculatorHelper.formatPrice;

/**
 * 平台首单优惠折扣的 {@link TradePriceCalculator} 实现类
 *
 * @author 山野羡民
 */
@Slf4j
@Component
@Order(TradePriceCalculator.ORDER_FIRST_ORDER_DISCOUNT)
public class FirstOrderDiscountPriceCalculator implements TradePriceCalculator {

    @Resource
    private FirstOrderDiscountApi firstOrderDiscountApi;
    @Resource
    @Lazy // 延迟加载，避免循环依赖
    private TradeOrderQueryService tradeOrderQueryService;

    @Override
    public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
        result.setFirstOrderDiscount(10D);
        // 非优惠活动订单，才计算该优惠
        if (Arrays.asList(TradeOrderTypeEnum.SECKILL.getType(), TradeOrderTypeEnum.BARGAIN.getType(), TradeOrderTypeEnum.COMBINATION.getType(), TradeOrderTypeEnum.POINT.getType())
                .contains(result.getType())) {
            log.debug("[calculate][只有非优惠活动订单({})，才处理首单优惠折扣]", result.getType());
            return;
        }
        if (ObjectUtil.equal(result.getType(), TradeOrderTypeEnum.GROUPON.getType())) {
            log.debug("[calculate][是团购套餐订单，不支持首单优惠折扣]");
            return;
        }
        //if (!firstOrderDiscountApi.hasEligibility(param.getUserId(), FirstOrderDiscountTypeEnum.NEW_VIP)) {
        //    log.debug("[calculate][用户({})，没有平台新会员资格，不享受首单优惠折扣", param.getUserId());
        //    return;
        //}
        if (!tradeOrderQueryService.isNewShopCustomer(result.getShopId(), param.getUserId())) {
            log.debug("[calculate][用户({})，不是商家新客，不享受首单优惠折扣", param.getUserId());
            return;
        }
        double discount = calculateDiscount(result);
        log.debug("[calculate][用户({})，首单优惠折扣基于销售价打{}折", param.getUserId(), discount);
        result.setFirstOrderDiscount(discount);
        if (!param.isUseFirstOrderDiscount()) {
            log.debug("[calculate][未指定使用首单优惠折扣({})，首单优惠 {} 折不生效]", param.getUserId(), discount);
            return;
        }
        // 计算每个 SKU 的优惠金额
        boolean flag = false;
        for (TradePriceCalculateRespBO.OrderItem orderItem : result.getItems()) {
            flag = true;
            // 计算价格
            Integer discountPrice = (int) (orderItem.getSkuPrice() - (orderItem.getSkuPrice() * discount / 10f));
            // 更新 SKU 的优惠金额
            orderItem.setDiscountPrice(discountPrice * orderItem.getCount());
            TradePriceCalculatorHelper.recountPayPrice(orderItem);
        }
        if (flag) {
            // 记录优惠明细
            List<Integer> discountPrices = result.getItems().stream().map(TradePriceCalculateRespBO.OrderItem::getDiscountPrice).toList();
            TradePriceCalculatorHelper.addPromotion(result, result.getItems(),
                    param.getUserId(), "首单优惠", PromotionTypeEnum.FIRST_ORDER_DISCOUNT.getValue(),
                    String.format("首单优惠：省 %s 元", formatPrice(discountPrices.stream().reduce(Integer::sum).orElse(0))),
                    discountPrices);
            TradePriceCalculatorHelper.recountAllPrice(result);
        }
        log.debug("[calculate][会员首单优惠折扣({})计算完成] {}", flag, result.getPrice());
    }

    private double calculateDiscount(TradePriceCalculateRespBO result) {
        // 按金额从高到低对首单折扣配置进行排序
        List<FirstOrderDiscountBO> configs = firstOrderDiscountApi.getDiscountConfig(result.getShopId())
                .stream()
                .sorted((o1, o2) -> o2.getAmount().compareTo(o1.getAmount()))
                .toList();
        for (FirstOrderDiscountBO config : configs) {
            if (result.getPrice().getTotalPrice() >= config.getAmount()) {
                return config.getDiscount();
            }
        }
        return 10D;
    }

}
